1mod function_id;
2pub use function_id::FunctionData;
3
4use crate::re::BSPointerHandle::ObjectRefHandle;
5use crate::re::TESGlobal::TESGlobal;
6use crate::re::TESObjectREFR::TESObjectREFR;
7use crate::re::TESQuest::TESQuest;
8use core::ffi::c_void;
9use core::ptr::NonNull;
10use core::{fmt, ptr};
11
12#[repr(u8)]
13#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum OpCode {
15 #[default]
17 Eq,
18 Ne,
20 Gt,
22 Ge,
24 Lt,
26 Le,
28}
29
30#[repr(C)]
32pub union GlobalOrFloat {
33 pub g: *mut TESGlobal,
34 pub f: f32,
35}
36const _: () = assert!(std::mem::size_of::<GlobalOrFloat>() == 0x8);
37
38impl GlobalOrFloat {
39 #[inline]
40 pub const fn new() -> Self {
41 Self { g: ptr::null_mut() }
42 }
43}
44
45#[derive(Debug)]
47pub enum ComparisonValue {
48 Global(*mut TESGlobal),
49 Float(f32),
50}
51
52impl Default for GlobalOrFloat {
53 #[inline]
54 fn default() -> Self {
55 Self { g: ptr::null_mut() }
56 }
57}
58
59bitflags::bitflags! {
60 #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
61 pub struct Flags: u8 {
62 const IS_OR = 0b00000001;
64 const USES_ALIASES = 0b00000010;
65 const GLOBAL = 0b00000100;
66 const USE_PACK_DATA = 0b00001000;
67 const SWAP_TARGET = 0b00010000;
68 }
70}
71
72impl Flags {
73 #[inline]
74 pub const fn new() -> Self {
75 Self::empty()
76 }
77
78 #[inline]
80 pub const fn op_code(&self) -> Option<OpCode> {
81 Some(match (self.bits() >> 5) & 0b111 {
83 0 => OpCode::Eq,
84 1 => OpCode::Ne,
85 2 => OpCode::Gt,
86 3 => OpCode::Ge,
87 4 => OpCode::Lt,
88 5 => OpCode::Le,
89 _ => return None, })
91 }
92}
93
94impl fmt::Debug for Flags {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 let mut flags = vec![];
97
98 if self.contains(Self::IS_OR) {
99 flags.push("IS_OR");
100 }
101 if self.contains(Self::USES_ALIASES) {
102 flags.push("USES_ALIASES");
103 }
104 if self.contains(Self::GLOBAL) {
105 flags.push("GLOBAL");
106 }
107 if self.contains(Self::USE_PACK_DATA) {
108 flags.push("USE_PACK_DATA");
109 }
110 if self.contains(Self::SWAP_TARGET) {
111 flags.push("SWAP_TARGET");
112 }
113
114 if let Some(op) = self.op_code() {
115 flags.push(match op {
116 OpCode::Eq => "Op::Eq",
117 OpCode::Ne => "Op::Ne",
118 OpCode::Gt => "Op::Gt",
119 OpCode::Ge => "Op::Ge",
120 OpCode::Lt => "Op::Lt",
121 OpCode::Le => "Op::Le",
122 });
123 } else {
124 flags.push("Op::Invalid");
125 }
126
127 f.debug_tuple("Flags").field(&flags.join(" | ")).finish()
128 }
129}
130
131#[commonlibsse_ng_derive_internal::to_bitflags]
132#[repr(u8)]
133#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
134pub enum ConditionItemObject {
135 #[default]
136 Self_ = 0,
137 Target = 1,
138 Ref = 2,
139 CombatTarget = 3,
140 LinkedRef = 4,
141 QuestAlias = 5,
142 PackData = 6,
143 EventData = 7,
144 CommandTarget = 8,
145}
146
147#[derive(Default)]
148#[repr(C)]
149pub struct CONDITION_ITEM_DATA {
150 pub comparisonValue: GlobalOrFloat, pub runOnRef: ObjectRefHandle, pub dataId: u32, pub functionData: FunctionData, pub flags: Flags, pub object: ConditionItemObject, pub pad32: u16, pub pad34: u32, }
159const _: () = assert!(core::mem::size_of::<CONDITION_ITEM_DATA>() == 0x30);
160
161impl CONDITION_ITEM_DATA {
162 #[inline]
163 pub const fn new() -> Self {
164 Self {
165 comparisonValue: GlobalOrFloat::new(),
166 runOnRef: ObjectRefHandle::new(),
167 dataId: 0,
168 functionData: FunctionData::new(),
169 flags: Flags::new(),
170 object: ConditionItemObject::Self_,
171 pad32: 0,
172 pad34: 0,
173 }
174 }
175
176 #[inline]
178 pub const fn comparison_value(&self) -> ComparisonValue {
179 unsafe {
180 if self.flags.contains(Flags::GLOBAL) {
181 ComparisonValue::Global(self.comparisonValue.g)
182 } else {
183 ComparisonValue::Float(self.comparisonValue.f)
184 }
185 }
186 }
187}
188
189impl fmt::Debug for CONDITION_ITEM_DATA {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 f.debug_struct("CONDITION_ITEM_DATA")
192 .field("comparisonValue", &self.comparison_value())
193 .field("runOnRef", &self.runOnRef)
194 .field("dataId", &self.dataId)
195 .field("functionData", &self.functionData)
196 .field("flags", &self.flags)
197 .field("object", &self.object)
198 .finish()
199 }
200}
201
202#[repr(C)]
203#[derive(Debug, PartialEq)]
204pub struct TESCondition {
205 pub head: Option<NonNull<TESConditionItem>>, }
207const _: () = assert!(core::mem::size_of::<TESCondition>() == 0x8);
208
209impl TESCondition {
210 #[inline]
211 pub const fn new() -> Self {
212 Self { head: None }
213 }
214
215 #[inline]
217 pub const fn is_empty(&self) -> bool {
218 self.head.is_none()
219 }
220
221 #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 29074, ae_id = 29888)]
223 pub fn is_true(&self, action_ref: *mut TESObjectREFR, target_ref: *mut TESObjectREFR) -> bool {}
224}
225
226impl Default for TESCondition {
227 #[inline]
228 fn default() -> Self {
229 Self::new()
230 }
231}
232impl Drop for TESCondition {
233 fn drop(&mut self) {
234 let mut cur = self.head;
235 while let Some(cur_ptr) = cur {
236 unsafe {
237 let next = cur_ptr.as_ref().next;
238 drop(Box::from_raw(cur_ptr.as_ptr()));
239 cur = next;
240 }
241 }
242 self.head = None;
243 }
244}
245
246#[derive(Debug)]
247#[repr(C)]
248pub struct ConditionCheckParams {
249 actionRef: *mut TESObjectREFR, targetRef: *mut TESObjectREFR, quest: *mut TESQuest, questStartEvent: *mut BGSStoryEvent, unk20: *mut c_void, unk28: bool, packageDataList: *mut BGSPackageDataList, }
257const _: () = assert!(core::mem::size_of::<ConditionCheckParams>() == 0x38);
258
259impl ConditionCheckParams {
260 #[inline]
261 pub const fn new(action_ref: *mut TESObjectREFR, target_ref: *mut TESObjectREFR) -> Self {
262 Self {
263 actionRef: action_ref,
264 targetRef: target_ref,
265 quest: ptr::null_mut(),
266 questStartEvent: ptr::null_mut(),
267 unk20: ptr::null_mut(),
268 unk28: false,
269 packageDataList: ptr::null_mut(),
270 }
271 }
272}
273
274#[derive(Debug)]
275#[repr(C)]
276pub struct TESConditionItem {
277 next: Option<NonNull<TESConditionItem>>, data: CONDITION_ITEM_DATA, }
280const _: () = assert!(core::mem::size_of::<TESConditionItem>() == 0x38);
281
282impl TESConditionItem {
283 #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 29090, ae_id = 29924)]
284 pub fn is_true(&self, solution: &mut ConditionCheckParams) -> bool {}
285}
286
287pub struct BGSPackageDataList;
288pub struct BGSStoryEvent;